package javalangspec;

public class MultipleLockingDemo {

	public static void main(String[] args) {
		final Victim victim = new Victim();
		Runnable r1 = new TestThread(victim), r2 = new TestThread(victim);
		
		new Thread(r1, "r1").start();
		new Thread(r2, "r2").start();
	}
	
}

class TestThread implements Runnable {

	private Victim victim;
	
	public TestThread(Victim victim) {
		this.victim = victim;
	}

	@Override
	public void run() {
		victim.m();
	}
	
}

class Victim {
	
	Object lock = new Object();
	
	public void m() {
		System.out.println(Thread.currentThread().getName() + " entered method!");
		
		synchronized (lock) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) { }
			
			System.out.println(Thread.currentThread().getName() + " hold first lock");
			synchronized (lock) {
				
				System.out.println(Thread.currentThread().getName() + " hold second lock");
				synchronized (lock) {
					System.out.println(Thread.currentThread().getName() + " hold third lock");
					synchronized (lock) {
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) { }
						System.out.println(Thread.currentThread().getName() + " hold last lock");
					}	
				}				
			}
		}
	}
	
}